﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NPOI.HSSF.UserModel;
using RuYiAdmin.Net.Common.CommonClass.Extensions;
using RuYiAdmin.Net.Common.Global;
using RuYiAdmin.Net.Common.Utility;
using RuYiAdmin.Net.Entity.BusinessDTO.SystemManagement;
using RuYiAdmin.Net.Entity.BusinessEntity.SystemManagement;
using RuYiAdmin.Net.Entity.BusinessEnum;
using RuYiAdmin.Net.Entity.CoreEntity;
using RuYiAdmin.Net.Entity.CoreEnum;
using RuYiAdmin.Net.Service.BusinessService.SystemManagement.Import;
using RuYiAdmin.Net.Service.BusinessService.SystemManagement.Role;
using RuYiAdmin.Net.Service.BusinessService.SystemManagement.RoleMenu;
using RuYiAdmin.Net.Service.BusinessService.SystemManagement.RoleOrg;
using RuYiAdmin.Net.Service.BusinessService.SystemManagement.RoleUser;
using RuYiAdmin.Net.WebApi.AppCode.Base;
using RuYiAdmin.Net.WebApi.AppCode.Filter;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace RuYiAdmin.Net.WebApi.Controllers.SystemManagement
{
    /// <summary>
    /// 角色管理控制器
    /// </summary>
    public class RoleManagementController : BaseController<SysRole>
    {
        /// <summary>
        /// 角色服务接口实例
        /// </summary>
        private readonly IRoleService roleService;

        /// <summary>
        /// 角色用户服务接口
        /// </summary>
        private readonly IRoleUserService roleUserService;

        /// <summary>
        /// 角色菜单服务接口
        /// </summary>
        private readonly IRoleMenuService roleMenuService;

        /// <summary>
        /// 导入配置服务接口
        /// </summary>
        private readonly IImportConfigService importConfigService;

        /// <summary>
        /// 角色机构服务接口
        /// </summary>
        private readonly IRoleOrgService roleOrgService;

        /// <summary>
        /// HttpContext
        /// </summary>
        private readonly IHttpContextAccessor context;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="roleService">角色服务实例</param>
        /// <param name="roleUserService">角色用户服务实例</param>
        /// <param name="roleMenuService">角色菜单服务实例</param>
        /// <param name="importConfigService">导入配置服务实例</param>
        /// <param name="roleOrgService">角色机构服务实例</param>
        ///<param name="context">Http会话实例</param>
        public RoleManagementController(IRoleService roleService, IRoleUserService roleUserService,
                                        IRoleMenuService roleMenuService, IImportConfigService importConfigService,
                                        IRoleOrgService roleOrgService, IHttpContextAccessor context) : base(roleService)
        {
            this.roleService = roleService;
            this.roleUserService = roleUserService;
            this.roleMenuService = roleMenuService;
            this.importConfigService = importConfigService;
            this.roleOrgService = roleOrgService;
            this.context = context;
        }

        /// <summary>
        /// 查询角色列表
        /// </summary>
        /// <param name="queryCondition">查询条件</param>
        /// <returns>ActionResult</returns>
        [HttpPost]
        [Log(OperationType.QueryList)]
        [Permission("role:query:list")]
        public IActionResult Post(QueryCondition queryCondition)
        {
            var sqlKey = "sqls:sql:query_sysrole";
            var strSQL = GlobalContext.Configuration.GetSection(sqlKey).Value;
            //获取用户机构编号
            var orgId = SessionContext.GetUserOrgId(this.context);
            strSQL = String.Format(strSQL, orgId);
            var actionResult = this.roleService.SqlQuery(strSQL, queryCondition);
            ////文件名
            //var fileName = "1636709374(1).jpg";
            ////存储路径
            //var path = Path.Join(GlobalContext.DirectoryConfig.GetTempPath(), "/");
            ////文件路径
            //var filePath = Path.Join(path, fileName);
            //var text = OCRUtil.Recognize(filePath);
            return Ok(actionResult);
        }

        /// <summary>
        /// 查询角色
        /// </summary>
        /// <param name="roleId">角色编号</param>
        /// <returns>ActionResult</returns>
        [HttpGet("{roleId}")]
        [Log(OperationType.QueryEntity)]
        [Permission("role:query:list")]
        public IActionResult GetById(Guid roleId)
        {
            var actionResult = this.roleService.GetById(roleId);
            return Ok(actionResult);
        }

        /// <summary>
        /// 新增角色
        /// </summary>
        /// <param name="role">角色对象</param>
        /// <returns>ActionResult</returns>
        [HttpPost]
        [Log(OperationType.AddEntity)]
        [Permission("role:add:entity")]
        public IActionResult Add([FromBody] SysRole role)
        {
            var actionResult = this.roleService.Add(role);

            var roleOrg = new SysRoleOrg();
            roleOrg.RoleId = role.Id;
            //获取用户
            var user = SessionContext.GetCurrentUserInfo(this.context);
            roleOrg.OrgId = user.OrgId.Equals(Guid.Empty) ? GlobalContext.SystemConfig.OrgRoot : user.OrgId;
            roleOrg.OwnerType = 0;
            this.roleOrgService.Add(roleOrg);

            return Ok(actionResult);
        }

        /// <summary>
        /// 编辑角色
        /// </summary>
        /// <param name="role">角色对象</param>
        /// <returns>ActionResult</returns>
        [HttpPut]
        [Log(OperationType.EditEntity)]
        [Permission("role:edit:entity")]
        public IActionResult Put([FromBody] SysRole role)
        {
            var actionResult = this.roleService.Update(role);
            return Ok(actionResult);
        }

        /// <summary>
        /// 删除角色
        /// </summary>
        /// <param name="roleId">角色编号</param>
        /// <returns>ActionResult</returns>
        [HttpDelete("{roleId}")]
        [Permission("role:del:entities")]
        [Log(OperationType.DeleteEntity)]
        public IActionResult Delete(Guid roleId)
        {
            if (this.Check(roleId))
            {
                return BadRequest("role has been used,can not be deleted.");
            }

            var actionResult = this.roleService.Delete(roleId);

            //删除角色与机构关系
            var roleOrgList = (List<SysRoleOrg>)this.roleOrgService.GetList().Object;
            roleOrgList = roleOrgList.Where(t => t.RoleId.Equals(roleId) && t.IsDel == 0 && t.OwnerType == 0).ToList();
            this.roleOrgService.DeleteRange(roleOrgList.Select(t => t.Id).ToArray());

            return Ok(actionResult);
        }

        /// <summary>
        /// 批量删除角色
        /// </summary>
        /// <param name="ids">编号数组</param>
        /// <returns>ActionResult</returns>
        [HttpDelete("{ids}")]
        [Permission("role:del:entities")]
        [Log(OperationType.DeleteEntity)]
        public IActionResult DeleteRange(String ids)
        {
            var array = StringUtil.GetGuids(ids);
            foreach (var item in array)
            {
                if (this.Check(item))
                {
                    return BadRequest("role has been used,can not be deleted.");
                }
            }

            var actionResult = this.roleService.DeleteRange(array);

            var roleOrgList = (List<SysRoleOrg>)this.roleOrgService.GetList().Object;
            var delList = new List<SysRoleOrg>();
            foreach (var item in array)
            {
                //删除角色与机构关系                
                roleOrgList = roleOrgList.Where(t => t.RoleId.Equals(item) && t.IsDel == 0 && t.OwnerType == 0).ToList();
                delList.AddRange(roleOrgList);
            }
            this.roleOrgService.DeleteRange(delList.Select(t => t.Id).ToArray());

            return Ok(actionResult);
        }

        /// <summary>
        /// 用户授权
        /// </summary>
        /// <param name="roleUsers">用户角色</param>
        /// <returns>ActionResult</returns>
        [HttpPost]
        [Log(OperationType.PermissionAuthorization)]
        [Permission("role:grant:permission")]
        public IActionResult GrantUserRole([FromBody] List<SysRoleUser> roleUsers)
        {
            var addList = new List<SysRoleUser>();
            if (roleUsers.Count > 0)
            {
                var list = (List<SysRoleUser>)this.roleUserService.GetList().Object;
                foreach (var item in roleUsers)
                {
                    var entity = list.Where(t => t.IsDel == 0 && t.UserId.Equals(item.UserId) && t.RoleId.Equals(item.RoleId)).FirstOrDefault();
                    if (entity == null)
                    {
                        addList.Add(item);
                    }
                }
            }
            var actionResult = this.roleUserService.AddList(addList);
            return Ok(actionResult);
        }

        /// <summary>
        /// 收回用户授权
        /// </summary>
        /// <param name="roleUsers">用户角色</param>
        /// <returns>ActionResult</returns>
        [HttpPost]
        [Log(OperationType.PermissionAuthorization)]
        [Permission("role:grant:permission")]
        public IActionResult WithdrawGrantedUserRole([FromBody] List<SysRoleUser> roleUsers)
        {
            var delList = new List<SysRoleUser>();
            if (roleUsers.Count > 0)
            {
                var list = (List<SysRoleUser>)this.roleUserService.GetList().Object;
                foreach (var item in roleUsers)
                {
                    var entity = list.Where(t => t.IsDel == 0 && t.UserId.Equals(item.UserId) && t.RoleId.Equals(item.RoleId)).FirstOrDefault();
                    if (entity != null)
                    {
                        delList.Add(entity);
                    }
                }
            }
            var actionResult = this.roleUserService.DeleteRange(delList.Select(t => t.Id).ToArray());
            return Ok(actionResult);
        }

        /// <summary>
        /// 获取授权的角色用户列表
        /// </summary>
        /// <param name="roleId">角色编号</param>
        /// <returns>ActionResult</returns>
        [HttpGet("{roleId}")]
        [Log(OperationType.QueryList)]
        [Permission("role:grant:permission")]
        public IActionResult GetGrantedUserRoles(Guid roleId)
        {
            var list = (List<SysRoleUser>)this.roleUserService.GetList().Object;
            list = list.Where(t => t.RoleId.Equals(roleId) && t.IsDel == 0).ToList();

            var actionResult = new Entity.CoreEntity.ActionResult();
            actionResult.HttpStatusCode = HttpStatusCode.OK;
            actionResult.Message = new String("OK");
            actionResult.Object = list;

            return Ok(actionResult);
        }

        /// <summary>
        /// 角色授权
        /// </summary>
        /// <param name="roleMenus">角色菜单</param>
        /// <returns>ActionResult</returns>
        [HttpPost]
        [Log(OperationType.MenuAuthorization)]
        [Permission("role:relate:menus")]
        public IActionResult GrantRoleMenus([FromBody] List<SysRoleMenu> roleMenus)
        {
            if (roleMenus.Count > 0)
            {
                var list = (List<SysRoleMenu>)this.roleMenuService.GetList().Object;
                list = list.Where(t => t.RoleId.Equals(roleMenus.FirstOrDefault().RoleId) && t.IsDel == 0).ToList();
                var ids = list.Select(t => t.Id).ToArray();
                this.roleMenuService.DeleteRange(ids);
            }

            var actionResult = this.roleMenuService.AddList(roleMenus);

            return Ok(actionResult);
        }

        /// <summary>
        /// 获取授权的角色菜单列表
        /// </summary>
        /// <param name="roleId">角色编号</param>
        /// <returns>ActionResult</returns>
        [HttpGet("{roleId}")]
        [Log(OperationType.QueryList)]
        [Permission("role:relate:menus")]
        public IActionResult GetGrantedRoleMenus(Guid roleId)
        {
            var list = (List<SysRoleMenu>)this.roleMenuService.GetList().Object;
            list = list.Where(t => t.RoleId.Equals(roleId) && t.IsDel == 0).ToList();

            var actionResult = new Entity.CoreEntity.ActionResult();
            actionResult.HttpStatusCode = HttpStatusCode.OK;
            actionResult.Message = new String("OK");
            actionResult.Object = list;

            return Ok(actionResult);
        }

        /// <summary>
        /// 获取继承角色的机构列表
        /// </summary>
        /// <param name="roleId">角色编号</param>
        /// <returns>ActionResult</returns>
        [HttpGet("{roleId}")]
        [Log(OperationType.QueryList)]
        [Permission("role:delegate:permission")]
        public IActionResult GetDelegatedRoleOrgs(Guid roleId)
        {
            var list = (List<SysRoleOrg>)this.roleOrgService.GetList().Object;
            list = list.Where(t => t.RoleId.Equals(roleId) && t.IsDel == 0 && t.OwnerType.Equals(1)).ToList();

            var actionResult = new Entity.CoreEntity.ActionResult();
            actionResult.HttpStatusCode = HttpStatusCode.OK;
            actionResult.Message = new String("OK");
            actionResult.Object = list;

            return Ok(actionResult);
        }

        /// <summary>
        /// 权限下放
        /// </summary>
        /// <param name="roleOrgs">角色机构列表</param>
        /// <returns>ActionResult</returns>
        [HttpPost]
        [Log(OperationType.DelegatePermission)]
        [Permission("role:delegate:permission")]
        public IActionResult DelegateRoleOrgs([FromBody] List<SysRoleOrg> roleOrgs)
        {
            //新增列表
            var addList = new List<SysRoleOrg>();
            //查询列表
            var list = (List<SysRoleOrg>)this.roleOrgService.GetList().Object;
            foreach (var item in roleOrgs)
            {
                if (list.Where(t =>
                                   t.IsDel == 0 &&
                                   t.RoleId.Equals(item.RoleId) &&
                                   t.OrgId.Equals(item.OrgId) &&
                                   t.OwnerType.Equals(0)).Count() > 0)
                {
                    //自有角色，无需继承
                    continue;
                }
                var count = list.Where(t =>
                                            t.IsDel == 0 &&
                                            t.RoleId.Equals(item.RoleId) &&
                                            t.OrgId.Equals(item.OrgId) &&
                                            t.OwnerType.Equals(item.OwnerType)).Count();
                //未继承该角色
                if (count == 0)
                {
                    addList.Add(item);
                }
            }
            //新增继承角色
            var actionResult = this.roleOrgService.AddList(addList);
            return Ok(actionResult);
        }

        /// <summary>
        /// 权限收回
        /// </summary>
        /// <param name="roleOrgs">角色机构列表</param>
        /// <returns>ActionResult</returns>
        [HttpPost]
        [Log(OperationType.DeleteEntity)]
        [Permission("role:delegate:permission")]
        public IActionResult WithdrawRoleOrgs([FromBody] List<SysRoleOrg> roleOrgs)
        {
            //删除列表
            var delList = new List<SysRoleOrg>();
            //查询列表
            var list = (List<SysRoleOrg>)this.roleOrgService.GetList().Object;
            foreach (var item in roleOrgs)
            {
                var entity = list.Where(t =>
                                            t.IsDel == 0 &&
                                            t.RoleId.Equals(item.RoleId) &&
                                            t.OrgId.Equals(item.OrgId) &&
                                            t.OwnerType.Equals(item.OwnerType)).FirstOrDefault();
                if (entity != null)
                {
                    delList.Add(entity);
                }
            }
            //删除继承角色
            var actionResult = this.roleOrgService.DeleteRange(delList.Select(t => t.Id).ToArray());
            return Ok(actionResult);
        }

        /// <summary>
        /// 查询是否为继承角色
        /// </summary>
        /// <param name="roleId">角色编号</param>
        /// <returns>ActionResult</returns>
        [HttpGet("{roleId}")]
        [Log(OperationType.QueryEntity)]
        [Permission("role:query:list")]
        public IActionResult IsInheritedRole(Guid roleId)
        {
            var actionResult = new Entity.CoreEntity.ActionResult();
            actionResult.HttpStatusCode = HttpStatusCode.OK;
            actionResult.Message = new String("OK");

            var roleOrgList = (List<SysRoleOrg>)this.roleOrgService.GetList().Object;

            if (roleOrgList.Where(t =>
                                     t.RoleId.Equals(roleId) &&
                                     t.IsDel == 0 &&
                                     t.OwnerType == 1 &&
                                     t.OrgId.Equals(SessionContext.GetUserOrgId(this.context))).
                           Count() > 0)
            {
                actionResult.Object = true;
            }
            else
            {
                actionResult.Object = false;
            }

            return Ok(actionResult);
        }

        /// <summary>
        /// 导出Excel
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Log(OperationType.ExportData)]
        [Permission("role:list:export")]
        public IActionResult ExportExcel()
        {
            var sqlKey = "sqls:sql:query_sysrole";
            var strSQL = GlobalContext.Configuration.GetSection(sqlKey).Value;
            //获取用户机构编号
            var orgId = SessionContext.GetUserOrgId(this.context);
            strSQL = String.Format(strSQL, orgId);
            var data = (List<SysRole>)this.roleService.SqlQuery(strSQL, new QueryCondition()).List.OrderBy(t => t.Order).ToList();
            var stream = data.Export().ToStream();
            stream.Position = 0;
            return File(stream, "application/octet-stream", "角色信息.xls");
        }

        /// <summary>
        /// Excel导入
        /// </summary>
        /// <param name="file">excel文件</param>
        /// <returns>ActionResult</returns>
        [HttpPost]
        [Log(OperationType.ImportData)]
        [Permission("role:list:import")]
        public IActionResult Import([FromForm] IFormFile file)
        {
            var actionResult = new Entity.CoreEntity.ActionResult();

            if (file != null)
            {
                #region 常规合法性校验

                //获取文件拓展名
                var extension = Path.GetExtension(file.FileName);
                //文件保存路径
                var filePath = FileUtil.SaveFormFile(file);

                var configDTO = this.importConfigService.GetImportConfig("RoleImportConfig");
                if (configDTO == null)
                {
                    return BadRequest("Import Config can not find!");
                }
                configDTO.ExcelPath = filePath;

                //常规合法性校验
                var errorCount = configDTO.ValidationDetecting();

                #endregion

                if (errorCount > 0)
                {
                    #region 常规校验出不合规项

                    actionResult.Object = errorCount;
                    actionResult.Message = configDTO.ExcelPath.Replace(extension, "").Split('/')[1];

                    #endregion
                }
                else
                {
                    #region 常规业务性校验

                    var roleList = (this.roleService.GetList().Object as List<SysRole>).Where(t => t.IsDel.Equals(0)).ToList();

                    var xlxStream = new FileStream(configDTO.ExcelPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);

                    var workbook = new HSSFWorkbook(xlxStream);
                    var worksheet = workbook.GetSheetAt(0);

                    for (var i = configDTO.StartRow; i <= worksheet.LastRowNum; i++)
                    {
                        var value = worksheet.GetRow(i).GetCell(1).GetCellValue().Trim();
                        if (!String.IsNullOrEmpty(value) && roleList.Where(t => t.RoleName.Equals(value)).Count() > 0)
                        {
                            errorCount++;
                            worksheet.SetCellComment(i, 1, "角色名称重复！");
                        }
                    }

                    #endregion

                    if (errorCount > 0)
                    {
                        #region 业务校验出不合规项

                        var xlxPath = configDTO.ExcelPath;

                        configDTO.ExcelPath = workbook.SaveAsXlx(xlxPath);

                        xlxStream.Close();
                        System.IO.File.Delete(xlxPath);

                        actionResult.Object = errorCount;
                        actionResult.Message = configDTO.ExcelPath.Replace(extension, "").Split('/')[1];

                        #endregion
                    }
                    else
                    {
                        #region 执行业务导入

                        //获取用户
                        var user = SessionContext.GetCurrentUserInfo(this.context);

                        for (var i = configDTO.StartRow; i <= worksheet.LastRowNum; i++)
                        {
                            var roleName = worksheet.GetRow(i).GetCell(1).GetCellValue().Trim();
                            var order = worksheet.GetRow(i).GetCell(2).GetCellValue();
                            var remark = worksheet.GetRow(i).GetCell(3).GetCellValue().Trim();

                            var role = new SysRole();
                            role.RoleName = roleName;
                            role.Order = String.IsNullOrEmpty(order) ? null : int.Parse(order);
                            role.Remark = remark;
                            this.roleService.Add(role);

                            var roleOrg = new SysRoleOrg();
                            roleOrg.RoleId = role.Id;
                            roleOrg.OrgId = user.OrgId.Equals(Guid.Empty) ? GlobalContext.SystemConfig.OrgRoot : user.OrgId;
                            roleOrg.OwnerType = 0;
                            this.roleOrgService.Add(roleOrg);
                        }

                        workbook.Close();
                        xlxStream.Close();

                        #endregion
                    }
                }
                actionResult.HttpStatusCode = HttpStatusCode.OK;
            }
            else
            {
                actionResult.HttpStatusCode = HttpStatusCode.NoContent;
                actionResult.Message = new String("NoContent");
            }

            return Ok(actionResult);
        }

        /// <summary>
        /// 角色检测
        /// </summary>
        /// <param name="roleId">角色编号</param>
        /// <returns>真假值</returns>
        private bool Check(Guid roleId)
        {
            var roleUserList = (List<SysRoleUser>)this.roleUserService.GetList().Object;
            var roleMenuList = (List<SysRoleMenu>)this.roleMenuService.GetList().Object;
            var roleOrgList = (List<SysRoleOrg>)this.roleOrgService.GetList().Object;

            if (roleUserList.Where(t => t.RoleId.Equals(roleId) && t.IsDel == 0).Count() > 0 ||
                roleMenuList.Where(t => t.RoleId.Equals(roleId) && t.IsDel == 0).Count() > 0 ||
                roleOrgList.Where(t => t.RoleId.Equals(roleId) && t.IsDel == 0 && t.OwnerType == 1).Count() > 0)
            {
                return true;
            }

            return false;
        }
    }
}
